/* examlib.c
 *
 * about examlib handle functions
 *
 * cproto command to create head file
 *   cproto examlib.c > examlib.h
 *
 * written by lasereden<lasereden@yeah.net> on March 4, 2002
 */

/*
Examine.Lib 试题库文件的结构如下：
struct {
  char[]          文件头字串 = "CometCASL Examine Library File"；
  char            EndOfFile = 0x1A；
  WORD            试题个数；
  struct[100] {   各试题消息；
    char[40] 试题的标题名；
    DWORD    偏移；
    WORD   长度；
  }
  char[]      试题正文，被 0xFF 异或。
*/

#include <stdio.h>

#include "casl.h"		/* including WORD, UWORD and DWORD define */
#include "tools.h"

#define EInfo_length 46

char *examlib_library = DOC_DIR "examine.lib";
structEInfo examlib_info[100];
char *examlib_title = NULL;
int examlib_number = 0;
int examlib_no = -1;

#include "examlib.h"

#include "support.h"

void display (char *format, ...);

/* ************************ Functions ************************ */

/* get full infomation of the examlib
 *   
 * args(input):
 *   void
 * output:
 *   library - library file name
 *   title - the title of the examlib. It must free while unuseful.
 *   infos[100] - infomations of all examinations
 *   no - let it -1(no choice)
 *   number - the number of examinations. also return
 */
int
examlib_information (void)
{
  FILE *fp;
  int i;

  examlib_number = 0;
  if (examlib_title != NULL)
    free (examlib_title);

  if ((fp = fopen (examlib_library, "r")) != NULL)
    {
      fseek (fp, 0, SEEK_SET);
      for (i = 0; fgetc (fp) != 0x1A; i++);
      fseek (fp, 0, SEEK_SET);
      if ((examlib_title = (char *) malloc (sizeof (char) * i)) != NULL)
	{
	  /* get examlib title */
	  fread (examlib_title, i + 1, 1, fp);
	  examlib_title[i] = '\0';

	  /* get the number of exams in the examlib */
	  fread (&examlib_number, sizeof (WORD), 1, fp);

	  /* EInfo of all exams in the examlib */
	  for (i = 0; i < examlib_number; i++)
	    fread (examlib_info + i, EInfo_length, 1, fp);

	  fclose (fp);
	  return examlib_number;
	}
      else
	fclose (fp);
    }

  return 0;			/* return zero if fail */
}

/* set examlib_no
 *
 * input:
 *   the name
 * output:
 *   examlib_no (also return) - is -1 if fail
 */
int
examlib_no_set (char *name)
{
  int i;

  examlib_no = -1;

  for (i = 0; i < examlib_number; i++)
    if (strcmp (examlib_info[i].name, name) == 0)
      break;
  if (i < examlib_number)
    examlib_no = i;

  return examlib_no;
}

/* get a question in the examlib
 * 
 * must execute examlib_information() first
 *
 *   examlib_no - what question in the examlib
 * return:
 *   question - malloc to save question. It must free while unuseful.
 */
char *
examlib_question (void)
{
  FILE *fp;
  char *question = NULL;
  int i;

  if (examlib_no >= 0 && examlib_no < examlib_number)	/* while examlib_no between 1 and examlib_number */
    {
      if ((question =
	   (char *) malloc (sizeof (char) * examlib_info[examlib_no].size)) !=
	  NULL)
	{
	  if ((fp = fopen (examlib_library, "r")) != NULL)
	    {
	      fseek (fp, examlib_info[examlib_no].offset, SEEK_SET);
	      for (i = 0; i < examlib_info[examlib_no].size; i++)
		{
		  question[i] = fgetc (fp) ^ 0xFF;
		  switch (question[i])
		    {
		    case '\0':
		      question[i] = '\n';
		      break;
		    case 0x01:
		      i--;
		      break;
		    case 0x02:
		      question[i] = '\0';
		      i = examlib_info[examlib_no].size;
		      break;
		    }
		}
	    }
	  else
	    {
	      free (question);
	      question = NULL;
	    }
	}
    }

  return question;
}

/* get a answer in the examlib 
 *
 *   examlib_no - what answer in the examlib
 * return:
 *   answer - malloc to save answer. It must free while unuseful.
 */
char *
examlib_answer (void)
{
  FILE *fp;
  int i, j, fill_size;
  char *answer = NULL, *fill;

  if (examlib_no >= 0 && examlib_no < examlib_number)	/* when examlib_no between 1 and examlib_number */
    {
      if ((fp = fopen (examlib_library, "r")) != NULL)
	{
	  fseek (fp, examlib_info[examlib_no].offset, SEEK_SET);
	  for (i = 0;
	       i < examlib_info[examlib_no].size
	       && (fgetc (fp) ^ 0xFF) != 0x02; i++);

	  fill_size = examlib_info[examlib_no].size - i;
	  if ((fill = (char *) malloc (sizeof (char) * fill_size)) != NULL)
	    {
	      fseek (fp, examlib_info[examlib_no].offset + i, SEEK_SET);
	      fread (fill, fill_size, 1, fp);
	      if ((answer =
		   (char *) malloc (sizeof (char) *
				    examlib_info[examlib_no].size)) != NULL)
		{
		  fseek (fp, examlib_info[examlib_no].offset, SEEK_SET);
		  for (i = 0, j = 0; i < examlib_info[examlib_no].size; i++)
		    {
		      answer[i] = fgetc (fp) ^ 0xFF;
		      switch (answer[i])
			{
			case '\0':
			  answer[i] = '\n';
			  break;
			case 0x01:
			  while ((answer[i++] = (fgetc (fp) ^ 0xFF)) != '\0');
			  i--;
			  j++;
			  while (j < fill_size
				 && (answer[i++] = fill[j++] ^ 0xFF));
			  answer[--i] = '\n';
			  break;
			case 0x02:
			  answer[i] = '\0';
			  i = examlib_info[examlib_no].size;
			  break;
			}
		    }
		}
	      free (fill);
	    }
	  fclose (fp);
	}
    }

  return answer;
}
